/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2021.
 * Description: support tasklock feature
 * Author: fanglinxu <fanglinxu@huawei.com>
 * Create: 2018-08-29
 */

#ifndef _LINUX_RTOS_TASKLOCK_H
#define _LINUX_RTOS_TASKLOCK_H

#ifdef CONFIG_RTOS_TASKLOCK

struct tasklock_info {
	unsigned long long mode;	    /* preempt disable or enable*/
	unsigned long long locktime;	    /* the disable start value */
	unsigned long long custom_timeout; /* timeout threshold for this task */
	unsigned long long set_tif;	    /* the value whether set the tif flag */
	long task_status_schedule;	    /* task status when entry __schedule */
	unsigned long long nivcsw;	    /* nonvoluntary context switches during tasklock */
};

struct rtos_tasklock_t {
	struct tasklock_info *tasklock_ctrl_page;
};

/* preempt disable, timeout control by tasklock_info->custom_timeout */
#define TASKLOCK_ENABLE_CUSTOM_TIMEOUT  2
/* preempt disable, timeout control by /proc/sys/kernel/sched_preempt_disable_timeout */
#define TASKLOCK_ENABLE_PROC_TIMEOUT    1
/* preempt enable */
#define TASKLOCK_DISABLE		0

extern struct tasklock_info *get_tasklock_page(struct task_struct *tsk);
extern void set_tasklock_page(struct task_struct *tsk, struct tasklock_info *page);

#define tasklock_mode(tsk)	\
		((*get_tasklock_page(tsk)).mode)

#define tasklock_locktime(tsk)	\
		((*get_tasklock_page(tsk)).locktime)

#define tasklock_custom_timeout(tsk) \
		((*get_tasklock_page(tsk)).custom_timeout)

#define tasklock_set_tif(tsk)	\
		((*get_tasklock_page(tsk)).set_tif)

#define tasklock_task_status_schedule(tsk)       \
		((*get_tasklock_page(tsk)).task_status_schedule)

#define tasklock_nivcsw(tsk)       \
		((*get_tasklock_page(tsk)).nivcsw)

extern void tasklock_task_fork(struct task_struct *tsk);
extern void tasklock_task_exit(struct task_struct *tsk);
extern void tasklock_sched_tick(void);
extern bool tasklock_skip_sched(bool preempt);
extern void tasklock_update_sched(void);
extern void tasklock_switch_count_collect(unsigned long **addr, struct task_struct *tsk);

extern int proc_pid_tasklock_status(struct seq_file *m,
	struct pid_namespace *ns, struct pid *pid, struct task_struct *task);

#ifdef CONFIG_RTOS_TASKLOCK_NOTIFIERS
extern struct blocking_notifier_head pagefault_in_notifier;
extern struct blocking_notifier_head pagefault_out_notifier;
extern struct blocking_notifier_head return_user_notifier;
#endif

#endif /* CONFIG_RTOS_TASKLOCK */

#endif /* _LINUX_RTOS_TASKLOCK_H */
